package com.huitone.smspfm.interfacz;

import java.io.FileInputStream;
import java.util.Arrays;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.logging.log4j.core.config.ConfigurationSource;
import org.apache.logging.log4j.core.config.Configurator;

import com.bin.common.utils.ArrayUtils;
import com.bin.common.utils.StringUtils;
import com.huitone.smspfm.interfacz.core.AppStaticConfigs;
import com.huitone.smspfm.interfacz.core.listener.OutSideCommandsHandler;
import com.huitone.smspfm.interfacz.core.listener.ShareMemoryCommandsListener;
import com.huitone.smspfm.interfacz.dao.entity.SvrNodeDef;
import com.huitone.smspfm.interfacz.exception.SimpleUncaughtExceptionHandler;
import com.huitone.smspfm.interfacz.logger.ExtLogger;
import com.huitone.smspfm.interfacz.mo.SvrNodeClientsManager;
import com.huitone.smspfm.interfacz.mo.deliver.SmsDeliverResendTask;
import com.huitone.smspfm.interfacz.mo.deliver.SmsDeliverTask;
import com.huitone.smspfm.interfacz.mo.report.SmsReportResendTask;
import com.huitone.smspfm.interfacz.mo.report.SmsReportTask;
import com.huitone.smspfm.interfacz.mt.MtMessageHandler;
import com.huitone.smspfm.interfacz.tasks.AutoMaticBlackListTask;
import com.huitone.smspfm.interfacz.tasks.CleanExpireMoRespSerialNoTask;
import com.huitone.smspfm.interfacz.tasks.CleanExpireRptRespSerialNoTask;
import com.huitone.smspfm.interfacz.tasks.ClientsHostPortTestTask;
import com.huitone.smspfm.interfacz.tasks.FileWriterTask;
import com.huitone.smspfm.interfacz.tasks.PickOutResendDeliversTask;
import com.huitone.smspfm.interfacz.tasks.PickOutResendReportsTask;
import com.huitone.smspfm.interfacz.tasks.ReloadConfigTimingTask;
import com.huitone.smspfm.interfacz.tasks.SmsPlatformSwitchTask;
import com.huitone.smspfm.interfacz.tasks.SmsSpeedStatisticsTask;
import com.huitone.smspfm.interfacz.validator.UserValidator;
import com.huitone.smspfm.socket.core.net.ExtSocketManager;
import com.huitone.smspfm.socket.server.SmsServer;

/**   
* @Title Main.java 
* @Package com.huitone.smspfm.interfacz 
* @Description TODO(用一句话描述该文件做什么) 
* @author ybliang   
* @date 2017年9月15日 下午6:30:59 
* @version V1.0   
*/
public class Main {
	
	static {
		try {
//			String path = Thread.currentThread().getContextClassLoader().getResource("log4j2.xml").getPath().substring(1).replace("/", "\\\\");
//			Configurator.initialize(null, new ConfigurationSource(new FileInputStream(path)));
			Configurator.initialize(null, new ConfigurationSource(new FileInputStream(System.getProperty("log4j2.xml"))));
		} catch (Exception e) {
			System.out.println("初始化log4j2配置文件时发生错误:" + e.getMessage());
		}
	}
	
	private static final ExtLogger logger = ExtLogger.create(Main.class);
	
	private static ShareMemoryCommandsListener listener = null;
	
	private static SmsServer server = null;
	
	private static ExtSocketManager socketManager = null;
	
	private static SmsReportTask smsReportTask = null;
	
	private static SmsReportResendTask smsReportResendTask = null;
	
	private static SmsDeliverTask smsDeliverTask = null;
	
	private static SmsDeliverResendTask smsDeliverResendTask = null;
	
	private static PickOutResendReportsTask pickOutResendReportsTask = null;
	
	private static PickOutResendDeliversTask pickOutResendDeliversTask = null;
	
	private static CleanExpireRptRespSerialNoTask cleanExpireRptRespSerialNoTask = null;
	
	private static CleanExpireMoRespSerialNoTask cleanExpireMoRespSerialNoTask = null;
	
	private static ClientsHostPortTestTask clientsHostPortTestTask = null;
	
	private static ReloadConfigTimingTask reloadConfigTimingTask = null;
	
	private static SmsSpeedStatisticsTask smsSpeedStatisticsTask = null;
	
	private static FileWriterTask smsFileWriterTask = null;
	
	private static AutoMaticBlackListTask autoMaticBlackListTask = null;
	



	public static void main(String[] args) {
		
		// 定义全局的未捕捉异常处理类
		Thread.setDefaultUncaughtExceptionHandler(new SimpleUncaughtExceptionHandler());
		
		// 全局参数初始化
		AppStaticConfigs.init();

		// 构建外部命令监听器,监听start,stop,reload等命令
		listener = new ShareMemoryCommandsListener();
		listener.setHandler(new OutSideCommandsHandler() {

			@Override
			public void stop(String[] args) {
				logger.info("stop:" + Arrays.asList(args));
				
				if (ArrayUtils.isEmpty(args)) {
					
					stopService();
					stopReportService();
					stopDeliverService();
					stopOtherTasks();
					
					// 清空上行报告及上行短信的客户端连接
					SvrNodeClientsManager.getInstance().destroy();
					
					listener.stopListener();
					
				} else {
					
					String param = args[0];
					
					if (StringUtils.equals(param, "lstservice")) {
						stopService();
					} else if (StringUtils.equals(param, "rptservice")) {
						stopReportService();
					} else if (StringUtils.equals(param, "dlvservice")) {
						stopDeliverService();
					} else if (StringUtils.equals(param, "othertasks")) {
						stopOtherTasks();
					}
				}
			}

			@Override
			public void start(String[] args) {
				logger.info("start:" + Arrays.asList(args));
				
				if (ArrayUtils.isEmpty(args)) {
					
					startOtherTasks();
					
				} else {
					
					String param = StringUtils.trim(args[0]);
					
					if (StringUtils.equalsIgnoreCase(param, "lstservice")) {
						startService();
					} else if (StringUtils.equals(param, "rptservice")) {
						startReportService();
					} else if (StringUtils.equals(param, "dlvservice")) {
						startDeliverService();
					} else if (StringUtils.equals(param, "othertasks")) {
						startOtherTasks();
					} 
				}
			}

			@Override
			public void reload(String[] args) {
				logger.info("reload:" + Arrays.asList(args));
				
				logger.info("短信平台接口程序重新加载配置参数...");
								
				
				AppStaticConfigs.reload();
				
				updatePersktsize(socketManager);
				
				updateInterceptIps(server);
				
				
				
			}

			

			@Override
			public void handle(String[] args) {
				logger.info("handle:" + Arrays.asList(args));
			}
		});
		listener.startListener();
	}
	
	/**
	 * 启动接口服务
	 */
	public static void startService() {
		
		logger.info("短信平台接口服务正在启动");
		
		if (server == null || !server.isAlive()) {
			
			socketManager = new ExtSocketManager();
			socketManager.setClearOutTimeSocketAutomatic(true);
			socketManager.setLimit(true);
			socketManager.setMaxSize(AppStaticConfigs.smspfmMaxSocket);
			
			server = new SmsServer()
					.setPort(AppStaticConfigs.smspfmServerPort)
					.setValidator(new UserValidator())
					.setSocketManager(socketManager)
					.setMessageHandler(new MtMessageHandler())
					//.setMessageHandlerClass(MtMessageHandler.class)
					//.setAutoResponse(true)
					.setBlackIps(AppStaticConfigs.blackIps)
					.setIgnoreIps(AppStaticConfigs.ignoreIps);
			server.startService();
			
			logger.info("短信平台接口服务启动完成");
			
		} else {
			if (!server.isKeepGoing()) {
				server = null;
				startService();
			} else {
				logger.info("短信平台接口服务正在运行");
			}
		}
	}
	
	/**
	 * 停止接口服务
	 */
	public static void stopService() {
		
		logger.info("短信平台接口服务正在关闭");
		
		if (server != null && server.isKeepGoing()) {
			server.stopService();
		}
		
		server = null;
		
		logger.info("短信平台接口服务已经关闭");
	}
	
	/**
	 * 启动状态报告推送任务
	 */
	public static void startReportService() {
		
		logger.info("短信平台接口正在启动状态报告推送任务");
		
		if (smsReportTask == null || !smsReportTask.isAlive()) {
			smsReportTask = new SmsReportTask();
			smsReportTask.start();
		}
		
		if (smsReportResendTask == null || !smsReportResendTask.isAlive()) {
			smsReportResendTask = new SmsReportResendTask();
			smsReportResendTask.start();
		}
		
		logger.info("短信平台接口状态报告推送任务启动完成");
	}
	
	/**
	 * 关闭状态报告推送任务
	 */
	public static void stopReportService() {
		
		logger.info("短信平台接口正在关闭状态报告推送任务");
		
		if (smsReportTask != null) {
			smsReportTask.destroy();
			smsReportTask = null;
		}
		if (smsReportResendTask != null) {
			smsReportResendTask.destroy();
			smsReportResendTask = null;
		}
		
		logger.info("短信平台接口状态报告推送任务已经关闭");
	}
	
	/**
	 * 启动上行短信推送任务
	 */
	public static void startDeliverService() {
		
		logger.info("短信平台接口上行短信推送任务正在启动");
		
		if (smsDeliverTask == null || !smsDeliverTask.isAlive()) {
			smsDeliverTask = new SmsDeliverTask();
			smsDeliverTask.start();
		}
		
		if (smsDeliverResendTask == null || !smsDeliverResendTask.isAlive()) {
			smsDeliverResendTask = new SmsDeliverResendTask();
			smsDeliverResendTask.start();
		}
		
		logger.info("短信平台接口上行短信推送任务启动完成");
	}
	
	/**
	 * 关闭上行短信推送任务
	 */
	public static void stopDeliverService() {
		
		logger.info("短信平台接口上行短信推送任务正在关闭");
		
		if (smsDeliverTask != null) {
			smsDeliverTask.destroy();
			smsDeliverTask = null;
		}
		
		if (smsDeliverResendTask != null) {
			smsDeliverResendTask.destroy();
			smsDeliverResendTask = null;
		}
		
		logger.info("短信平台接口上行短信推送任务已经关闭");
	}
	
	public static void startOtherTasks() {
		
		logger.info("短信平台接口启动数据维护线程任务");
		
		// 启动线程挑出需要重发的状态报告
		if (pickOutResendReportsTask == null || !pickOutResendReportsTask.isAlive()) {
			pickOutResendReportsTask = new PickOutResendReportsTask();
			pickOutResendReportsTask.start();
		}
		
		// 启动线程挑出需要重发的上行短信
		if (pickOutResendDeliversTask == null || !pickOutResendDeliversTask.isAlive()) {
			pickOutResendDeliversTask = new PickOutResendDeliversTask();
			pickOutResendDeliversTask.start();
		}
		
		// 清理接口过期的重复检测序列
		// new CleanExpireSerialsTask().start();
		
		// 清理过期的接入接口收到的报告响应信息序列元素
		if (cleanExpireRptRespSerialNoTask == null || !cleanExpireRptRespSerialNoTask.isAlive()) {
			cleanExpireRptRespSerialNoTask = new CleanExpireRptRespSerialNoTask();
			cleanExpireRptRespSerialNoTask.start();
		}
		
		// 清理过期的接口收到的上行响应信息序列元素
		if (cleanExpireMoRespSerialNoTask == null || !cleanExpireMoRespSerialNoTask.isAlive()) {
			cleanExpireMoRespSerialNoTask = new CleanExpireMoRespSerialNoTask();
			cleanExpireMoRespSerialNoTask.start();
		}
		
		// 客户端报告及上行短信推送地址:端口连通性测试
		if (AppStaticConfigs.clientConnCheckTaskOn) {
			if (clientsHostPortTestTask == null || !clientsHostPortTestTask.isAlive()) {
				clientsHostPortTestTask = new ClientsHostPortTestTask();
				clientsHostPortTestTask.start();
			}
		}
		
		// 是否打开定时重载配置信息任务
		if (AppStaticConfigs.reloadConfigTimingOnOff) {
			if (reloadConfigTimingTask == null || !reloadConfigTimingTask.isAlive()) {
				reloadConfigTimingTask = new ReloadConfigTimingTask();
				reloadConfigTimingTask.start();
			}
		}
		

		if(AppStaticConfigs.speedControl){
			//启动定时任务，清理本地流量统计和同步redis缓存
			if(smsSpeedStatisticsTask == null || !smsSpeedStatisticsTask.isAlive()){
				smsSpeedStatisticsTask = new SmsSpeedStatisticsTask();
				smsSpeedStatisticsTask.start();
			}
		}
		
		//
		if(smsFileWriterTask == null || !smsFileWriterTask.isAlive()){
			smsFileWriterTask = new FileWriterTask();
			smsFileWriterTask.start();
		}
		
		if(autoMaticBlackListTask == null || ! autoMaticBlackListTask.isAlive()){
			autoMaticBlackListTask = new AutoMaticBlackListTask();
			autoMaticBlackListTask.start();
		}
		
		logger.info("短信平台接口数据维护线程任务启动完成");
		
	}
	
	public static void stopOtherTasks() {
		
		logger.info("短信平台接口数据维护线程任务正在关闭");
		
		if (pickOutResendReportsTask != null) {
			pickOutResendReportsTask.destroy();
			pickOutResendReportsTask = null;
		}
		
		if (pickOutResendDeliversTask != null) {
			pickOutResendDeliversTask.destroy();
			pickOutResendDeliversTask = null;
		}
		
		if (cleanExpireRptRespSerialNoTask != null) {
			cleanExpireRptRespSerialNoTask.destroy();
			cleanExpireRptRespSerialNoTask = null;
		}
		
		if (cleanExpireMoRespSerialNoTask != null) {
			cleanExpireMoRespSerialNoTask.destroy();
			cleanExpireMoRespSerialNoTask = null;
		}
		
		if (clientsHostPortTestTask != null) {
			clientsHostPortTestTask.destroy();
			clientsHostPortTestTask = null;
		}
		
		if (reloadConfigTimingTask != null) {
			reloadConfigTimingTask.destroy();
			reloadConfigTimingTask = null;
		}
		
		if(smsSpeedStatisticsTask != null){
			smsSpeedStatisticsTask.destroy();
			smsSpeedStatisticsTask = null;
		}
		
		if(smsFileWriterTask != null){
			smsFileWriterTask.destroy();
			smsFileWriterTask = null;
		}
		
		if(autoMaticBlackListTask != null){
			autoMaticBlackListTask.destroy();
			autoMaticBlackListTask = null;
		}
		
		logger.info("短信平台接口数据维护线程任务已经关闭");
	}
	
	/**
	 * 更新客户端最大的连接数
	 * @param socketManager
	 */
	private static void updatePersktsize(ExtSocketManager socketManager) {
		
		if (socketManager != null) {
			Map<String, SvrNodeDef> svrNodeDefMap = AppStaticConfigs.svrNodeDefMap;
			Iterator<Entry<String, SvrNodeDef>> iterator = svrNodeDefMap.entrySet().iterator();
			while(iterator.hasNext()) {
				Entry<String, SvrNodeDef> entry = iterator.next();
				String svrNode = entry.getKey();
				SvrNodeDef svrNodeDef = entry.getValue();
				Integer conNum = svrNodeDef.getConNum();
				socketManager.addPersktsize(svrNode, conNum == null ? 0 : conNum);
			}
		}
		
	}
	
	/**
	 * 更新黑名单IP及忽略名单IP
	 * @param smsServer
	 */
	private static void updateInterceptIps(SmsServer smsServer) {
		
		if (smsServer != null) {
			smsServer.setBlackIps(AppStaticConfigs.blackIps);
			smsServer.setIgnoreIps(AppStaticConfigs.ignoreIps);
		}
	}
	
	
	
}
